package alarm

import (
	"encoding/json"
	"strings"
	"time"

	"github.com/didi/nightingale/src/models"
	"github.com/didi/nightingale/src/modules/monapi/acache"
	"github.com/didi/nightingale/src/modules/monapi/config"

	"github.com/toolkits/pkg/logger"
	"github.com/toolkits/pkg/net/httplib"
)

func getEndpointBindings(endpoint string) ([]string, error) {
	list := make([]string, 0)
	resouceIds, err := models.ResourceIdsByIdents([]string{endpoint})
	if err != nil {
		return list, err
	}

	nodeIds, err := models.NodeIdsGetByResIds(resouceIds)
	if err != nil {
		return list, err
	}

	for _, id := range nodeIds {
		node, err := models.NodeGet("id=?", id)
		if err != nil {
			return list, err
		}

		if node == nil {
			continue
		}

		list = append(list, node.Path)
	}
	return list, nil
}

func DoWebhook(event *models.Event) {
	stra, exists := acache.StraCache.GetById(event.Sid)
	if !exists {
		logger.Warningf("sid not found, event: %v", event)
		return
	}

	detail := []models.EventDetail{}

	if err := json.Unmarshal([]byte(event.Detail), &detail); err != nil {
		logger.Warningf("event detail unmarshal failed, err: %v", err)
		return
	}

	userIds := []int64{}
	if err := json.Unmarshal([]byte(event.Users), &userIds); err != nil {
		logger.Warningf("event detail unmarshal event.users, err: %v", err)
		return
	}

	users, err := models.UserGetByIds(userIds)
	if err != nil {
		logger.Warningf("get users err: %v", err)
		return
	}

	usernames := []string{}
	for _, user := range users {
		usernames = append(usernames, user.Username)
	}

	teamIds := []int64{}
	if err := json.Unmarshal([]byte(event.Groups), &teamIds); err != nil {
		logger.Warningf("event detail unmarshal event.groups, err: %v", err)
		return
	}

	teams, err := models.TeamGetByIds(teamIds)
	if err != nil {
		logger.Warningf("get teams err: %v", err)
		return
	}

	groups := []string{}
	for _, team := range teams {
		groups = append(groups, team.Ident)
	}

	endpointBindingArray, err := getEndpointBindings(event.Endpoint)
	var endpointBindings string
	if err != nil || len(endpointBindingArray) == 0 {
		endpointBindings = event.NodePath
	} else {
		endpointBindings = strings.Join(endpointBindingArray, ", ")
	}
	webhookEvent := CallbackEvent{
		Id:          event.Id,
		Sid:         event.Sid,
		Sname:       event.Sname,
		NodePath:    endpointBindings,
		Endpoint:    event.Endpoint,
		Priority:    event.Priority,
		EventType:   event.EventType,
		Category:    event.Category,
		Status:      event.Status,
		HashId:      event.HashId,
		Etime:       event.Etime,
		Value:       event.Value,
		Info:        event.Info,
		Created:     event.Created,
		Started:     event.Started,
		Nid:         event.Nid,
		Detail:      detail,
		Groups:      groups,
		Users:       usernames,
		LastUpdator: stra.LastUpdator,
	}

	for _, backend := range config.Get().Webhook {
		header := map[string]string{}
		if backend.Token != "" {
			header["Authorization"] = "Bearer " + backend.Token
		}

		req := httplib.Post(backend.Addr).SetTimeout(3 * time.Second)
		for k, v := range header {
			req = req.Header(k, v)
		}
		res, err := req.JSONBodyQuiet(webhookEvent).String()
		logger.Debugf("Webhook, api:%s, event:%+v, error:%v, response:%s", backend.Addr, webhookEvent, err, res)
	}
}
